package tcplib

import (
	"MqttCloudProtocolServer/ProtocolServer/mqttlib"
	"MqttCloudProtocolServer/publiclib/datamodel"
	"MqttCloudProtocolServer/publiclib/datamodel/dborm"
	"MqttCloudProtocolServer/publiclib/helplib"
	"net"
	"strconv"
	"time"

	"github.com/wonderivan/logger"
)

//TCPServerDirect TCP收发服务器
type TCPServerDirect struct {
	mqttlib.OperatorBase
	//tcp          *datamodel.TCPClient
	dbtcp        *dborm.Manageserver
	listener     net.Listener
	receiver     func(key string, buffer []uint8)
	currentFrame *frameObject
	isRunning    bool
}

//Start Fun 如果启动监听失败（端口被占用），则5秒重试
func (_this *TCPServerDirect) Start() bool {
	_this.isRunning = true
	for !_this.listenPort(_this.dbtcp.HostIP, _this.dbtcp.HostPort) {
		time.Sleep(time.Second * 5)
	}
	return true
}

//listenPort 监听端口
func (_this *TCPServerDirect) listenPort(ip string, port int) bool {
	listener, err := net.Listen("tcp", ip+":"+strconv.Itoa(int(port)))
	_this.listener = listener
	go _this.useBuffer() //
	if err != nil {
		logger.Alert("server :: error listen:", err)
		return false
	}
	for _this.isRunning {
		if conn, err := _this.listener.Accept(); err != nil {
			logger.Alert("server :: accept error:", err)
			break
		} else {
			//为了不阻塞新的连接接入，采用协程接收与处理数据
			go _this.receiceData(conn)
			//_this.conns.Push(conn)
		}
	}
	return true
}

//Modify Fun
func (_this *TCPServerDirect) Modify(params interface{}) bool {
	switch params.(type) {
	case *datamodel.TCPClient:
		//_this.tcp = params.(*datamodel.TCPClient)
		break
	case *dborm.Manageserver:
		_this.dbtcp = params.(*dborm.Manageserver)
		break
	default:
		return false
	}
	return true
}

//Close Fun
func (_this *TCPServerDirect) Close() bool {
	_this.isRunning = false
	/*for !_this.conns.IsEmpty() {
		conn := _this.conns.Pull().(net.Conn)
		if err := conn.Close(); err != nil {
			logger.Info(err)
		}
	}*/
	if err := _this.listener.Close(); err != nil {
		logger.Error(err)
	}
	return true
}

//receiceData 循环接收数据，frameBuffer的生产者
func (_this *TCPServerDirect) receiceData(conn net.Conn) {
	var buffer = make([]byte, 1024)
	var retryCount = 0
	defer conn.Close()
	for _this.isRunning {
		if length, e := conn.Read(buffer); e != nil {
			if e.Error() == "EOF" {
				logger.Debug("读到EOF结束")
				retryCount = 0
				return
			}
			logger.Alert("server :: read error:", e)
			time.Sleep(time.Second)
			retryCount++
			if retryCount > 5 {
				retryCount = 0
				return
			}
		} else {
			logger.Debug("server :: read data ")
			if _this.isRunning {
				_this.currentFrame = &frameObject{buffer[:length], conn, time.Now()}
				if _this.dbtcp.Protocol == ModbusTCPDirect {
					_this.receiver(_this.GetKey(), _this.rtu2tcpReceiveDeal(buffer[:length]))
				} else {
					_this.receiver(_this.GetKey(), buffer[:length])
				}
			}
			retryCount = 0
		}
	}
}

//useBuffer 处理buffer积存，frameBuffer的消费者
func (_this *TCPServerDirect) useBuffer() {
	/*for _this.isRunning {
		tmpFram := <-_this.frameBuffer
		tempBuffer := tmpFram.buffer
		//tmpSpan := time.Now().Sub(tmpFram.timeFlag).Seconds() * 1000
		if (time.Now().Sub(tmpFram.timeFlag).Seconds() * 1000) > float64(_this.timeout) {
			logger.Warn(_this.GetKey() + ":报文已超时，抛弃一帧")
			continue
		}
		if _this.dbtcp.Protocol == ModbusTCP {
			tempBuffer = _this.rtu2tcpReceiveDeal(tempBuffer)
		}
		_this.receiver(_this.GetKey(), tempBuffer)
		_this.currentFrame = &tmpFram

		//先等待接收。等待超时则抛弃一帧
		if _this.rwLocker.Wait() {
			//等待超时
			logger.Warn(_this.GetKey() + ":报文等待超时，抛弃一帧")
		} else {
			//等待不超时，发送报文帧也已经出队列
			logger.Trace(_this.GetKey() + ":等待完成")
		}
	}*/
}

//SendData Fun
func (_this *TCPServerDirect) SendData(buffer []uint8) bool {
	tempFrame := _this.currentFrame

	if tempFrame == nil {
		logger.Alert(_this.GetKey() + ":当前连接为空，无法发送" + helplib.BufferToString(buffer))
		return false
	} else if _this.dbtcp.Protocol == ModbusTCPDirect /*"MODBUS_RTU_2_TCP"*/ {
		if len(tempFrame.buffer) < 6 {
			logger.Alert(_this.GetKey() + ":原报文长度错误，无法判断报文头" + helplib.BufferToString(tempFrame.buffer))
			return false
		}
		var index = tempFrame.buffer[:2]
		if !_this.checkFrame(buffer, tempFrame.buffer, _this.dbtcp.Protocol) {
			logger.Alert("报文校验错误")
			return false
		}
		buffer = _this.rtu2tcpSendDeal(buffer, index)
	}
	if buffer != nil {
		if _, err := tempFrame.conn.Write(buffer); err != nil {
			logger.Alert(err)
		}
	} else {
		logger.Alert("buffer is nil")
	}
	return true
}
func (_this *TCPServerDirect) checkFrame(sbuffer, rbuffer []uint8, protocol int) bool {
	if sbuffer == nil || rbuffer == nil || len(sbuffer) < 2 || len(rbuffer) < 7 {
		logger.Warn("报文错误，不处理本次报文")
		return false
	}
	if protocol == ModbusTCPDirect /*"MODBUS_RTU_2_TCP"*/ {
		return sbuffer[0] == rbuffer[6]
	}
	return sbuffer[0] == rbuffer[0]
}

//SetReceive Fun
func (_this *TCPServerDirect) SetReceive(callback func(key string, buffer []uint8)) {
	_this.receiver = callback
}

func (_this *TCPServerDirect) rtu2tcpSendDeal(buffer, index []uint8) []uint8 {
	if index == nil || len(index) != 2 {
		logger.Alert("处理发送数据crc时当前帧长度错误" + helplib.BufferToString(index))
		return nil
	}
	if buffer == nil || len(buffer) < 4 {
		logger.Alert("待处理数据帧长度不正常" + helplib.BufferToString(buffer))
		return nil
	}
	logger.Trace("send: " + helplib.BufferToString(buffer))
	length := len(buffer) - 2
	title := append(index, []uint8{0, 0, uint8((length & 0xff00) >> 8), uint8(length & 0x00ff)}...)
	tempbuff := buffer[:length]
	tempbuff2 := append(title, tempbuff...)
	return tempbuff2
}

func (_this *TCPServerDirect) rtu2tcpReceiveDeal(buffer []uint8) []uint8 {
	if len(buffer) < 7 {
		logger.Alert("接收的Modbus报文错误，长度不足")
		return []uint8{}
	}
	rtudata := buffer[6:]
	crc := helplib.CheckSum(rtudata)
	tempbuff := append(rtudata, crc...)

	logger.Trace("receive: " + helplib.BufferToString(tempbuff))
	return tempbuff
}
